package com.qf.myrbac.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qf.myrbac.annotation.OperationLog;
import com.qf.myrbac.sys.entity.SysRole;
import com.qf.myrbac.sys.dao.SysRoleDao;
import com.qf.myrbac.sys.entity.SysRoleDept;
import com.qf.myrbac.sys.entity.SysRoleMenu;
import com.qf.myrbac.sys.service.SysRoleDeptService;
import com.qf.myrbac.sys.service.SysRoleMenuService;
import com.qf.myrbac.sys.service.SysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.myrbac.utils.PageQueryUtil;
import com.qf.myrbac.utils.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author 徐英海
 * @since 2022-10-27
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRole> implements SysRoleService {
    @Autowired
    private SysRoleMenuService roleMenuService;
    @Autowired
    private SysRoleDeptService roleDeptService;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PageVo<SysRole> queryByPage(Map<String, Object> params) {
        Page<SysRole> page = PageQueryUtil.getPage(params);
        Object name = params.get("roleName");
        String roleName = name != null ? name.toString() : null;
        LambdaQueryWrapper<SysRole> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(StringUtils.isNotBlank(roleName), SysRole::getRoleName, roleName);
        this.page(page, roleQueryWrapper);
        return new PageVo<SysRole>(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(optName = "新增角色")
    @Override
    public void saveRoleAndAll(SysRole sysRole) {
        sysRole.setCreateTime(new Date());
        this.save(sysRole);
        //2.保存角色和菜单的对应关系
        List<Long> menuIdList = sysRole.getMenuIdList();
        Long roleId = sysRole.getRoleId();
        List<SysRoleMenu> roleMenuList = menuIdList.stream()
                .map(menuId -> new SysRoleMenu(roleId, menuId))
                .collect(Collectors.toList());
        roleMenuService.saveBatch(roleMenuList);
        //3.保存角色和部门的对应关系
        List<Long> deptIdList = sysRole.getDeptIdList();
        List<SysRoleDept> roleDeptList = deptIdList.stream()
                .map(deptId -> new SysRoleDept(roleId, deptId))
                .collect(Collectors.toList());
        roleDeptService.saveBatch(roleDeptList);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public SysRole getRoleById(Long roleId) {
        SysRole role = this.getById(roleId);
        //查角色对应的菜单
        QueryWrapper<SysRoleMenu> roleMenuQueryWrapper = new QueryWrapper<>();
        roleMenuQueryWrapper.select("menu_id");
        roleMenuQueryWrapper.eq("role_id", roleId);
        List<Object> menuIdList = roleMenuService.listObjs(roleMenuQueryWrapper);
        List<Long> menuIds = menuIdList.stream()
                .map(menuId -> Long.parseLong(menuId.toString()))
                .collect(Collectors.toList());
        role.setMenuIdList(menuIds);
        //查询角色对应的部门信息
        QueryWrapper<SysRoleDept> roleDeptQueryWrapper = new QueryWrapper<>();
        roleDeptQueryWrapper.select("dept_id");
        roleDeptQueryWrapper.eq("role_id", roleId);
        List<Object> deptIdList = roleDeptService.listObjs(roleDeptQueryWrapper);
        List<Long> deptIds = deptIdList.stream()
                .map(deptId -> Long.parseLong(deptId.toString()))
                .collect(Collectors.toList());
        role.setDeptIdList(deptIds);
        return role;
    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(optName = "修改角色")
    @Override
    public void updateAndAll(SysRole role) {
        this.updateById(role);
        List<Long> menuIdList = role.getMenuIdList();
        List<Long> deptIdList = role.getDeptIdList();
        Long roleId = role.getRoleId();
        UpdateWrapper<SysRoleMenu> roleMenuUpdateWrapper = new UpdateWrapper<>();
        UpdateWrapper<SysRoleDept> roleDeptUpdateWrapper = new UpdateWrapper<>();
        roleMenuUpdateWrapper.eq("role_id", roleId);
        roleDeptUpdateWrapper.eq("role_id", roleId);
        roleMenuService.remove(roleMenuUpdateWrapper);
        roleDeptService.remove(roleDeptUpdateWrapper);
        roleMenuService.saveBatch(
                menuIdList.stream()
                        .map(menuId -> new SysRoleMenu(roleId, menuId))
                        .collect(Collectors.toList())
        );
        roleDeptService.saveBatch(
                deptIdList.stream()
                        .map(deptId -> new SysRoleDept(roleId, deptId))
                        .collect(Collectors.toList())
        );
    }

    @Transactional(rollbackFor = Exception.class)
    @OperationLog(optName = "删除角色")
    @Override
    public void removeAndAll(Long[] ids) {
        UpdateWrapper<SysRole> roleUpdateWrapper = new UpdateWrapper<>();
        UpdateWrapper<SysRoleMenu> roleMenuUpdateWrapper = new UpdateWrapper<>();
        UpdateWrapper<SysRoleDept> roleDeptUpdateWrapper = new UpdateWrapper<>();
        roleUpdateWrapper.in("role_id", ids);
        roleMenuUpdateWrapper.in("role_id", ids);
        roleDeptUpdateWrapper.in("role_id", ids);
        this.remove(roleUpdateWrapper);
        roleMenuService.remove(roleMenuUpdateWrapper);
        roleDeptService.remove(roleDeptUpdateWrapper);
    }
}
